/**
  * 搭建koa框架配置路由
  * @module 框架搭建
 * @author 徐灿
 * @date 2018-9-6
  */
'use strict';

const fs = require('fs');
const path = require('path');
const moment = require('moment');
const Koa = require('koa');
const mount = require('koa-mount');
const Router = require('koa-router');
const session = require('koa-session');
const body = require('koa-better-body');
const staticServer = require('koa-static');
const log = require('../services/log/Log');

function mkDir(err) {
    if (err && err.code !== 'EEXIST') {
        console.error(err.message);
    }
}

function staticDir(dir) {
    return staticServer(path.join(__dirname, dir));
}

async function Server(port) {
    const app = new Koa();
    const router = new Router();
    const config = {
        key: 'koa:sess',
        maxAge: 'session',
        overwrite: true,
        httpOnly: true,
        signed: true,
        rolling: false
    };

    app.keys = ['some secret hurr'];

    fs.mkdir('./upload', mkDir);
    fs.mkdir('./appFile',mkDir);
    fs.mkdir('./export', mkDir);
    fs.mkdir('./log', mkDir);

    router.all('*', async function (ctx, next) {
        let start = new Date();
        try {
            let url = ctx.req._parsedUrl.pathname;

            if (url === '/favicon.ico') {
                let favicon = require(`./routes/favicon`);
                await favicon.apply(ctx, arguments);
            } else {
                let middleware = require(`./routes${url}`);
                // if (url !== '/' && url !== '/signIn') {
                //     if (!ctx.session.user || !ctx.session.user.user_id) {
                //         throw new Error('Session已失效，请重新登录');
                //     }
                // }
                await middleware.apply(ctx, arguments);
            }
        } catch (err) {
            ctx.body = {success: false, message: err.message};
            let time = moment().format('YYYY-MM-DD HH:mm:ss');
            let errStr =
                `
======================================================================
[${time}]
${err.stack}
`;
            fs.appendFile(`./log/${moment().format('YYYY-MM-DD')}.log`, errStr);

            // TODO 需要根据不同级别的错误使用warn或者error，暂时先全部使用error。
            console.error(`${ctx.method} ${ctx.res.statusCode} ${Date.now() - start}ms ${ctx.originalUrl} ${errStr}`);
        }
    });

    app
        .use(mount('/css', staticDir('../web/css')))
        .use(mount('/font', staticDir('../web/font')))
        .use(mount('/fonts', staticDir('../web/fonts')))
        .use(mount('/img', staticDir('../web/img')))
        .use(mount('/upload', staticDir('../../upload')))
        .use(mount('/js', staticDir('../web/js')))
        .use(mount('/ext', staticDir('../web/sdk/extjs-6.5')))
        .use(mount('/jQuery', staticDir('../web/sdk/jQuery')))
        .use(mount('/echarts', staticDir('../web/sdk/echarts')))
        .use(mount('/tools', staticDir('../web/sdk/tools')))
        .use(mount('/tyLog', staticDir('../../log')))
        .use(session(config, app))
        .use(log.koa)
        .use(body({
            uploadDir: './upload',
            keepExtensions: true,
            formLimit: "5mb",
            jsonLimit: "5mb",
            textLimit: "5mb"
        }))
        .use(router.routes())
        .use(router.allowedMethods())
        .on('error', function (err, ctx) {
            let time = moment().format('YYYY-MM-DD HH:mm:ss');
            let errStr =
                `
======================================================================
[${time}]
${err.stack}
`;
            fs.appendFile(`./log/${moment().format('YYYY-MM-DD')}.log`, errStr);
            if (ctx) {
                let str = `${ctx.method} ${ctx.res.statusCode} ${ctx.originalUrl} ${errStr}`;
                console.error(str);
            } else {
                console.error(err);
            }
        })
        .listen(port);
}

async function listen(port) {
    await Server(port);
}

exports.listen = listen;